﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Moq;

namespace MvcWiki.Test.Repository.FileSystem.WikiNamespaceFileSystemRepository
{
    public class GetWikiNamespaceFacts
    {
        [Fact]
        public void Returns_WikiNamespace_By_Name()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");
        }

        [Fact]
        public void Returns_WikiNamespace()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            Assert.Equal("Namespace", wikiNamespace.Name);
        }

        [Fact]
        public void Checks_Whether_Namespace_Directory_Exists()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Checks_Whether_FileExists()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Throws_Exception_If_Namespace_Directory_Does_Not_Exists()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { });

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            Assert.Throws<MvcWiki.Exceptions.NamespaceDoesNotExistException>(
                () => repository.GetWikiNamespace("Namespace"));
        }

        [Fact]
        public void Throws_Exception_If_File_Does_Not_Exists()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(false);

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            Assert.Throws<MvcWiki.Exceptions.NamespaceDoesNotExistException>(
                () => repository.GetWikiNamespace("Namespace"));
        }

        [Fact]
        public void Reads_Namespace_Xml_File()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Reads_Markup_From_Page_Xml_File()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Returns_WikiNamespace_With_WikiMarkup()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();

            var wikiMarkup = new MvcWiki.Model.WikiMarkup { Name = "StandardMarkup" };
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            wikiMarkupProvider.Setup(x => x.CreateWikiMarkup("StandardMarkup")).Returns(wikiMarkup);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            Assert.Equal<MvcWiki.Model.WikiMarkup>(wikiMarkup, wikiNamespace.Markup);
        }

        [Fact]
        public void Returns_WikiNamespace_With_Id()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            Assert.Equal<string>("9f878f77-21bb-4fb1-a68e-3cd2c61201cc", wikiNamespace.Id.ToString());
        }

        [Fact]
        public void Calls_IUnitOfWork_Selected()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();
            unitOfWork.Setup(x => x.Selected(It.IsAny<MvcWiki.Model.WikiNamespace>(), It.IsAny<MvcWiki.Repository.IUnitOfWorkPersistence>()));

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            MvcWiki.Model.WikiNamespace wikiNamespace = repository.GetWikiNamespace("Namespace");

            unitOfWork.VerifyAll();
        }

        [Fact]
        public void Calls_IWikiMarkupProvider()
        {
            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();

            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            wikiMarkupProvider.Setup(x => x.CreateWikiMarkup("StandardMarkup"));

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", "Namespace---*")).Returns(new string[] { "c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc" });
            fileSystem.Setup(x => x.FileExists("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns(true);
            fileSystem.Setup(x => x.ReadFromFile("c:\\path\\Namespace---9f878f77-21bb-4fb1-a68e-3cd2c61201cc\\wikinamespace.xml")).Returns("<wikinamespace><wikimarkup>StandardMarkup</wikimarkup></wikinamespace>");

            var repository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            repository.GetWikiNamespace("Namespace");

            wikiMarkupProvider.VerifyAll();
        }
    }
}